home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Precision Software Appli…tions Silver Collection 4
/
Precision Software Applications Silver Collection Volume 4 (1993).iso
/
stats
/
chadyn.exe
/
YXWINDOW.C
< prev
Wrap
C/C++ Source or Header
|
1988-12-08
|
15KB
|
451 lines
/* YWINDOWS - routines for dealing with X Windows. */
#include "yinclud.h"
#ifdef X11
#include <X11/Xutil.h>
#include <setjmp.h>
#define BESTWIDTH 640
#define BESTHEIGHT 480
#define MINPIXELS 400
#define BACKSPACE '\010'
#define RUBOUT '\177'
#define LINEKILL '\025'
#define RETURN '\015'
#define EOT '\004'
#define MAXPTS 50
#define iserase(x) ((x) == BACKSPACE || (x) == RUBOUT)
#define isprintable(x) ((x) == '\n' || (x) >= '\040' && (x) <= '\176')
#define bscrt() {putchar(BACKSPACE); putchar(' '); putchar(BACKSPACE);}
static char kbbuf[MAXCHAR + 1];/* keystroke buffer */
static int bufcount = 0; /* number of chars in kbbuf */
#define progname *argvGlob
#define streq(x, y) (strcmp(x, y) == 0)
#define QUIT exit(1)
#define die(x) {fprintf(stderr, "%s: %s(file %s, line %d)\n", progname, x,\
__FILE__, __LINE__); QUIT; }
XSizeHints sizehint = {
PAllHints, /* flags */
100, 100, /* user specified x, y */
BESTWIDTH, BESTHEIGHT,/* user specified width, height */
BESTWIDTH, BESTHEIGHT,/* program spec. min width, height */
BESTHEIGHT * 2, BESTHEIGHT * 2,
/* program spec. max width, height */
100, 100, /* program spec. width, height inc */
{ 1, 2 }, /* min aspect */
{ 3, 1 } /* max aspect */
};
jmp_buf key_env; /* used by AWAITKEY to save stack state as we wait
* for a key to be pressed */
/* -------------------------------------------------------------------- */
/* SETVIDMODE - initialize X windows */
SetVidMode() {
XWindowAttributes swa, gswa;
char *option;
int val;
if((x_dpy = XOpenDisplay(NULL)) == NULL)
die("can't get display");
x_screennbr = DefaultScreen(x_dpy);
/* Get user's favorite values for foreground, background, and
* width of window border. First initialize a default background.
*/
x_backcolor = BlackPixel(x_dpy, x_screennbr);
x_forecolor = WhitePixel(x_dpy, x_screennbr);
if((option = XGetDefault(x_dpy, progname, "BorderWidth")) != NULL &&
(val = atoi(option)) > 1)
x_borderwidth = val;
if((option = XGetDefault(x_dpy, progname, "Background")) != NULL) {
if(streq(option, "black"))
x_backcolor = BlackPixel(x_dpy, x_screennbr);
else
x_backcolor = WhitePixel(x_dpy, x_screennbr);
}
if((option = XGetDefault(x_dpy, progname, "Foreground")) != NULL) {
if(streq(option, "black"))
x_forecolor = BlackPixel(x_dpy, x_screennbr);
else
x_forecolor = WhitePixel(x_dpy, x_screennbr);
}
if(x_backcolor == x_forecolor) {
fprintf(stderr, "%s: identical background & foreground\n:",
progname);
x_backcolor = WhitePixel(x_dpy, x_screennbr);
x_forecolor = BlackPixel(x_dpy, x_screennbr);
}
/* Create a window */
if((x_window = XCreateSimpleWindow(x_dpy, DefaultRootWindow(x_dpy),
sizehint.x, sizehint.y, sizehint.width, sizehint.height,
x_borderwidth, x_forecolor, x_backcolor)) == 0)
die("XCreateSimpleWindow failed");
XSetStandardProperties(x_dpy, x_window, "Dynamics", "Dynamics",
None, argvGlob, argcGlob, &sizehint);
/* Use the default color map and set gravity(I still don't understand
* this yet)
*/
/* swa.colormap = DefaultColormap(x_dpy, x_screennbr); */
swa.bit_gravity = CenterGravity;
XChangeWindowAttributes(x_dpy, x_window, CWBitGravity,
&swa);
/* Create a Graphics Context for this window, using the selected
* values of foreground and background color
*/
x_gcval.foreground = x_forecolor;
x_gcval.background = x_backcolor;
x_gc = XCreateGC(x_dpy, x_window, GCForeground | GCBackground,
&x_gcval);
/* Do likewise for blanking out stuff */
x_gcval.foreground = x_backcolor;
x_gcval.background = x_forecolor;
x_gcblank = XCreateGC(x_dpy, x_window, GCForeground | GCBackground,
&x_gcval);
/* We are interested in Exposure events, KeyPressed events,
* and mouse motions
*/
XSelectInput(x_dpy, x_window, x_eventmask);
/* Now map the window to the screen */
XMapWindow(x_dpy, x_window);
/* Query the window size */
(void) XGetWindowAttributes(x_dpy, x_window, &gswa);
scrncols = gswa.width;
scrnrows = gswa.height;
return;
}
/* -------------------------------------------------------------------- */
/* SETPIXEL - turn on the pixel at P.
* Normally we save up the points to be plotted in a buffer and plot
* them all at once with one call to XDrawPoints in order to save the
* overhead of many calls to the X server. However, when we are in
* single step mode (cycle > 0), then we plot one dot at a time.
*/
setPixel(p)
POINT *p;
{
#ifdef NEW
XDrawPoint(x_dpy, x_window, x_gc, p->x, p->y);
#else
static XPoint ptbuf[MAXPTS];
static int ptcount = 0;
if(cycle > 0) {
if(ptcount > 0) { /* dump buffered pts to screen */
ptbuf[ptcount].x = p->x;
ptbuf[ptcount].y = p->y;
ptcount++;
XDrawPoints(x_dpy, x_window, x_gc, ptbuf, ptcount,
CoordModeOrigin);
ptcount = 0;
} else
XDrawPoint(x_dpy, x_window, x_gc, p->x, p->y);
} else {
ptbuf[ptcount].x = p->x; /* buffer & plot when full */
ptbuf[ptcount].y = p->y;
ptcount++;
if(ptcount == MAXPTS) {
XDrawPoints(x_dpy, x_window, x_gc, ptbuf, ptcount,
CoordModeOrigin);
ptcount = 0;
}
}
return;
#endif /* NEW */
}
/* -------------------------------------------------------------------- */
/* SCR_CLR - clear the window. */
scr_clr()
{
/* We need to remember whether the crosses are on, so that we
* can clear the background in the pixmaps behind them
* before we redraw them on the screen.
*/
int need0 = IsCross0Set;
int need1 = IsCross1Set;
if(need0)
turnoff(BIGCROSS);
if(need1)
turnoff(SMALLCROSS);
XClearWindow(x_dpy, x_window);
if(need0) {
cross(crossX0, crossY0, SCRNCROSSWIDTH, SCRNCROSSHEIGHT, SCRN,
BIGCROSS);
IsCross0Set = 1;
}
if(need1) {
cross(crossX1, crossY1, SCRNCROSSWIDTH / 2,
SCRNCROSSHEIGHT / 2, SCRN, SMALLCROSS);
IsCross1Set = 1;
}
return;
}
/* -------------------------------------------------------------------- */
/* Basic routines for handling the keyboard using X windows. */
/* -------------------------------------------------------------------- */
/* MAPKEY - examine both the KeySym code for the pressed key and the character
* translation to determine whether we have an alphabetic keystroke or some
* other key, like an arrow key.
* XLOOKUPSTRING maps arrow keys to ascii characters so we need to distinguish
* between them.
*/
int mapkey(symbol, ch)
register KeySym symbol;
register int ch;
{
if(symbol == XK_Delete || symbol == XK_BackSpace ||
ch == BACKSPACE) { /* map to backspace */
symbol = (KeySym) BACKSPACE;
} else if(symbol == XK_Return || symbol == XK_Linefeed ||
ch == RETURN || ch == LINEFEED) { /* map to control-M */
symbol = (KeySym) RETURN;
} else if(ch == LINEKILL) { /* map to line kill char */
symbol = (KeySym) LINEKILL;
} else if(ch == EOT) { /* control-D for EOF */
symbol = (KeySym) 0;
} else if(symbol == XK_Escape) {
symbol = (KeySym) ch; /* ASCII escape */
} else
symbol = (KeySym) ch;
return((int) symbol);
}
/* -------------------------------------------------------------------- */
/* KEYCHECK - return 0 if no key has been hit. Otherwise return the KeySym of
* the most recently struck character. The typed character is NOT stored in
* the keyboard buffer!
*/
int keycheck()
{
XEvent event;
KeySym symbol = (KeySym) 0;
char ch;
if(XCheckTypedWindowEvent(x_dpy, x_window, KeyPress, &event))
(void) XLookupString(&event, &ch, 1, &symbol, NULL);
return(mapkey(symbol, (int) ch));
}
/* -------------------------------------------------------------------- */
/* ALARMHANDLE - spring back to the start of AWAITKEY when the latter
* times out.
*/
int alarmhandle()
{
(void) signal(SIGALRM, SIG_DFL);
longjmp(key_env, 1);
return(1); /* never happens */
}
/* -------------------------------------------------------------------- */
/* AWAITKEY - like KEYCHECK except we block until a key is struck.
* The typed character is NOT stored in the keyboard buffer.
* We return NUL if no key is struck within TIMEOUT seconds.
* A TIMEOUT value of 0 means to wait forever.
*/
int awaitkey(timeout)
unsigned timeout; /* in seconds */
{
XEvent event;
KeySym symbol;
char ch;
if(timeout != 0) {
(void) signal(SIGALRM, alarmhandle);
(void) alarm(timeout);
}
if(setjmp(key_env) == 0) { /* wait for a key */
XWindowEvent(x_dpy, x_window, KeyPressMask, &event);
(void) XLookupString(&event, &ch, 1, &symbol, NULL);
} else /* timed out */
symbol = (KeySym) 0;
(void) alarm(0); /* cancel the alarm */
return(mapkey(symbol, (int) ch));
}
/* -------------------------------------------------------------------- */
/* CHKKEYSTATUS - return 1 if a key has been hit and 0 otherwise.
* We keep the keypressed event in the queue however so that keycheck()
* can later determine which key has been pressed.
*/
int ChkKeyStatus()
{
XEvent event;
Bool yes;
if(yes = XCheckWindowEvent(x_dpy, x_window, KeyPressMask, &event))
XPutBackEvent(x_dpy, &event);
return((int) yes);
}
/* -------------------------------------------------------------------- */
/* STOREKEY - Get the next character typed from the graphics window and
* place into the keyboard buffer, manually performing erase and line kill
* processing. Return the character typed.
* Notes:
* 1. We call XWindowEvent to block until a character is read.
* 2. We let backspace(control-H) and rubout(DELETE) erase characters,
* and control-U(NAK) erase the line, regardless of the current
* terminal settings.
* 3. It is important that a NUL be placed in KBBUF at the logical
* end of the buffer. That is, we have two ways to track the exent of its
* contents: the value of BUFCOUNT and the location of the NUL.
* 4. If the contents of the keyboard buffer would overflow, the excess
* characters are silently discarded.
* 5. Carriage returns are not mapped to newlines in X windows; they are read
* as control-M's from the keyboard and converted to newlines here.
* 6. No word erase or line-redraw processing is available in this version.
* 7. Control-D is mapped to NUL to simulate an EOF.
* 8. Keys which are not standard ASCII characters (e.g. arrow keys)
* have the proper keysym code returned, but this is mapped in turn
* to an ASCII character. (For example, the up arrow key is mapped
* to a capital R, I think, in the buffer, but the function returns
* an integer code between 128 and 255 so that the value of the function,
* interpreted as a KeySym, correctly indicates that an arrow key has
* been pressed.)
*/
int storekey()
{
XEvent event;
char ch;
KeySym symbol = (KeySym) 0;
/* Get all pending KeyPress events and place in the buffer.
* If the buffer overflows, silently discard the excess characters.
* We have to do extra checking of CH and SYMBOL because the latter
* mapping doesn't handle control-key combinations.
*/
XWindowEvent(x_dpy, x_window, KeyPressMask, &event);
if(bufcount < MAXCHAR &&
XLookupString(&event, &ch, 1, &symbol, NULL) > 0) {
symbol = (KeySym) mapkey(symbol, (int) ch);
switch(symbol) {
case BACKSPACE: /* erase only on current line */
if(bufcount > 0 && kbbuf[bufcount-1] != RETURN)
kbbuf[--bufcount] = '\0';
break;
case RETURN:
kbbuf[bufcount++] = RETURN;
break;
case LINEKILL: { /* erase current line only */
register char *b = kbbuf + bufcount - 1;
while(bufcount > 0 && *b != RETURN) {
*b-- = '\0';
bufcount--;
}
}
break;
case '\0': /* end of file */
kbbuf[bufcount] = '\0';
break;
default:
kbbuf[bufcount++] = ch;
break;
}
}
return((int) symbol);
}
/* -------------------------------------------------------------------- */
/* GETKBS - get a string from the keyboard buffer, if available.
* A string is considered available if a newline character is in the buffer.
* All characters are copied from the buffer into STRING up to the newline;
* the newline is replaced with a NUL in STRING, and the contents of
* KBBUF are bumped down to the front.
* Return value is the number of characters copied. If no newline exists,
* then STRING is unchanged and the function returns 0. No check is made
* for overflow in STRING.
*/
int getkbs(string)
char *string;
{
register char *b;
register char *s = string;
register int k;
for(b = kbbuf; *b != RETURN && *b != '\0'; b++); /* find newline */
if(*b == RETURN) {
for(b = kbbuf; *b != RETURN; b++)
*s++ = *b;
*s++ = '\0'; /* return at least 1 */
k = (int) (b - kbbuf) + 1; /* +1 to skip newline */
for(b = kbbuf; k < bufcount; k++) /* bump down buffer */
*b++ = kbbuf[k];
*b = '\0'; /* this is very important! */
bufcount = (int) (b - kbbuf);
}
return((int) (s - string));
}
/* -------------------------------------------------------------------- */
/* CRTECHO - echo the typed character to the screen.
* N is the number of characters typed so far. If the character is LINEKILL
* (NAK), then erase to the beginning of the line. All printable characters
* are echoed. Control characters that are not printing characters are
* echoed as percent signs.
* Note: We echo backspace-space-backspace to erase characters.
*/
void crtecho(ch, n)
register int ch;
register int n;
{
register int j;
if(iserase(ch) && n > 0) {
bscrt();
} else if(ch == LINEKILL) {
for(j = 0; j < n; j++) {
bscrt();
}
} else if(isprintable(ch)) {
putchar(ch);
}
else
putchar('%');
fflush(stdout);
return;
}
/* -------------------------------------------------------------------- */
/* XWFGETS - get a string from the keyboard buffer. Manually perform all
* input editing and echoing to the standard output(assumed to be the
* screen.) The routine copies characters until a newline is scanned,
* blocking for the reads if needed.
* The keyboard buffer contents are copied down as needed.
* The function returns a pointer to a static string which is overwritten
* on each call.
*/
char *xwfgets() {
static char string[MAXCHAR + 1];
register int n;
register int ch;
if(getkbs(string) > 0)
printf("%s\n", string);
else {
for(n = 0; (ch = storekey()) != RETURN; n++)
if(ch != '\0')
crtecho(ch, n);
crtecho('\n', n); /* place final newline */
(void) getkbs(string);
}
return(&string[0]);
}
/* -------------------------------------------------------------------- */
setRGBColor()
{
PRINT "Color is not implemented under X windows\n");
return;
}
#endif /* X11 */